#include <stdio.h>
#include "assert.h"
#include <pthread.h>
#include <stdlib.h>

typedef struct  lock_ticket {
    int ticket;
    int turn;
} lock_t;

lock_t flag;

 void lock_init() {
    flag.ticket = 0;
    flag.turn   = 0;
}

 void lock() {
    int myturn = 1;

    //atomic fetch and add
    //equal to myturn = __sync_fetch_and_add (&flag.ticket, 1)  ，将1加到flag.ticket， 并返回flag.ticket的“旧”值给myturn
    
    myturn = __sync_fetch_and_add (&flag.ticket, 1);
   /* asm volatile (
            "lock xaddl %0, %1"
            : "+r" (myturn),  "+m" (flag.ticket) // the varaiable to be added
            :      // value to be added                       
            : "memory", "cc"
    );*/
    
    while (flag.turn != myturn)
        ; // spin
}

 void unlock() {
	int value = 1;
        asm volatile (
            "lock xaddl %0, %1"
            :"+r"(value), "+m" (flag.turn)
            :                        
            : "memory", "cc"
    );
 }


long sum = 0;
long N = 100000;

void *T_sum(void *tid) {
    for (int i = 0; i < N; i++) {
        lock();
	assert(flag.ticket - flag.turn <= 2 && flag.ticket >= flag.turn);
        for (int _ = 0; _ < 10; _++) {
            sum++;
        }
       unlock();
    }
    printf("Thread id: %d, sum: %ld \n", tid, sum);
    pthread_exit(NULL); 
}


int main() {
pthread_t threads[2];
    int status, i;
    for(i=0; i < 2; i++){ 
        printf("Main here. Creating thread %d\n", i);
        status = pthread_create(&threads[i], NULL, T_sum, (void *)i); 
        if (status != 0) {
            printf("Oops. pthread_create returned error code %d\n", status); 
            exit(-1);
        }
    }
    for (i=0; i < 2; i++){ pthread_join(threads[i], NULL);}
    printf("sum: %ld \n", sum);
}
